/*
 *
 *  Copyright (C) 2012-2024
 *  All rights reserved, Designed By 杭州连线客信息技术有限公司
 *  注意：
 *  本软件为杭州连线客信息技术有限公司开发研制，未经购买不得使用
 *  购买后可获得全部源代码（禁止转卖、分享、上传到码云、github等开源平台）
 *  一经发现盗用、分享等行为，将追究法律责任，后果自负
 *
 */

package com.lxk.oms.postorder.flow.craete;

import cn.hutool.core.util.ObjectUtil;
import com.lxk.oms.order.domain.vo.OmsOrderItemVo;
import com.lxk.oms.order.domain.vo.OmsOrderVo;
import com.lxk.oms.order.service.IOmsOrderItemService;
import com.lxk.oms.postorder.domain.bo.OmsPostOrderBo;
import com.lxk.oms.postorder.domain.bo.OmsPostOrderItemBo;
import com.lxk.oms.postorder.domain.enums.PostOrderEnums;
import com.lxk.oms.postorder.domain.req.CreatePostOrderReq;
import com.lxk.service.idgenerator.GeneratorType;
import com.lxk.service.idgenerator.IdGeneratorServiceApi;
import com.yomahub.liteflow.annotation.LiteflowComponent;
import com.yomahub.liteflow.core.NodeComponent;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.dromara.common.core.exception.ServiceException;

import java.math.BigDecimal;
import java.util.List;
import java.util.Map;

import static com.lxk.oms.postorder.flow.craete.FlowPostOrderNodeConst.POST_ORDER_ORIGINAL_AMOUNT;

/**
 * 售后订单价格计算节点
 *
 * @author heyi
 * 2024/9/28
 */
@Slf4j
@LiteflowComponent(POST_ORDER_ORIGINAL_AMOUNT)
@AllArgsConstructor
public class PostOrderOriginalAmountNode extends NodeComponent {
    private final IdGeneratorServiceApi idGeneratorServiceApi;
    private final IOmsOrderItemService omsOrderItemService;


    @Override
    public void process() throws Exception {
        CreatePostOrderReq req = this.getRequestData();
        PostOrderCreateContext context = this.getContextBean(PostOrderCreateContext.class);
        OmsOrderVo omsOrder = context.getOmsOrder();
        Long orderId = omsOrder.getId();
        Long merId = omsOrder.getMerId();
        Long userId = context.getUserId();
        List<OmsOrderItemVo> omsOrderItemVos = context.getOmsOrderItemVos();
        Map<Long, OmsOrderItemVo> orderItemVoMap = omsOrderItemService.convertToMap(omsOrderItemVos);
        List<CreatePostOrderReq.PostOrderItem> postOrderItemList = req.getPostOrderItemList();
        List<OmsPostOrderItemBo> postOrderItemBoList = postOrderItemList.stream().map(item -> buildItem(item, orderItemVoMap, orderId, merId, userId)).toList();
        context.setPostOrderItemBoList(postOrderItemBoList);
        OmsPostOrderBo add = buildPostOrder(omsOrder, orderId, context, postOrderItemBoList);
        context.setPostOrderBo(add);
    }

    /**
     * 构建退款订单
     *
     * @param omsOrder
     * @param orderId
     * @param context
     * @param postOrderItemBoList
     * @return
     */
    private OmsPostOrderBo buildPostOrder(OmsOrderVo omsOrder, Long orderId, PostOrderCreateContext context, List<OmsPostOrderItemBo> postOrderItemBoList) {
        BigDecimal actPayPrice = omsOrder.getActPayPrice();
        OmsPostOrderBo add = new OmsPostOrderBo();
        add.setPostType(context.getPostOrderType().getPostOrderType());
        add.setOrderSn(omsOrder.getOrderNo());
        add.setOrderId(orderId);
        add.setPostOrderNo(idGeneratorServiceApi.generatorSn(GeneratorType.POST_ORDER));
        add.setOrderType(omsOrder.getOrderType());
        add.setMerId(omsOrder.getMerId());
        add.setExplainImg(context.getExplainImg());
        add.setExplains(context.getExplains());
        add.setReasons(context.getReasons());
        add.setStatus(PostOrderEnums.PostOrderStatus.REVIEW.getPostOrderStatus());
        add.setUserId(omsOrder.getUserId());
        add.setUserIp(context.getUserIp());
        BigDecimal refundAmount = calRefundAmount(postOrderItemBoList, context);
        add.setRefundAmount(refundAmount);
        add.setRefundCount(calRefundCount(postOrderItemBoList));
        add.setActRefundAmount(refundAmount);
        add.setGoodStatus(context.getGoodStatus());
        if (actPayPrice.compareTo(refundAmount) < 0) {
            add.setActRefundAmount(actPayPrice);
        }
        return add;
    }

    /**
     * 计算退款金额逻辑
     *
     * @param postOrderItemBoList
     * @param context
     * @return
     */
    private BigDecimal calRefundAmount(List<OmsPostOrderItemBo> postOrderItemBoList, PostOrderCreateContext context) {
        BigDecimal totalRefundAmount = postOrderItemBoList.stream().map(OmsPostOrderItemBo::getRefundAmount).reduce(BigDecimal::add).orElse(BigDecimal.ZERO);
        BigDecimal actPayPrice = context.getOmsOrder().getActPayPrice();
        // 超出支付金额时，按照实际实付金额去处理
        if (totalRefundAmount.compareTo(actPayPrice) > 0) {
            return actPayPrice;
        }
        return totalRefundAmount;
    }

    /**
     * 计算退款商品数量
     *
     * @param postOrderItemBoList
     * @return
     */
    private Integer calRefundCount(List<OmsPostOrderItemBo> postOrderItemBoList) {
        return postOrderItemBoList.stream().map(OmsPostOrderItemBo::getRefundCount).reduce(Integer::sum).orElse(0);
    }

    /**
     * 构建退款订单子项
     *
     * @param item
     * @param orderItemVoMap
     * @param orderId
     * @param merId
     * @param userId
     * @return
     */
    private OmsPostOrderItemBo buildItem(CreatePostOrderReq.PostOrderItem item, Map<Long, OmsOrderItemVo> orderItemVoMap, Long orderId, Long merId, Long userId) {
        Long orderItemId = item.getOrderItemId();
        Long skuId = item.getSkuId();
        Integer count = item.getCount();
        Long spuId = item.getSpuId();
        OmsOrderItemVo omsOrderItemVo = orderItemVoMap.get(orderItemId);
        Long orderItemSpuId = omsOrderItemVo.getSpuId();
        Long orderItemSkuId = omsOrderItemVo.getSkuId();
        String skuName = omsOrderItemVo.getSkuName();
        String spuName = omsOrderItemVo.getSpuName();
        String picUrl = omsOrderItemVo.getPicUrl();
        BigDecimal price = omsOrderItemVo.getPrice();
        // 校验参数
        checkParams(skuId, orderItemSkuId, spuId, orderItemSpuId, omsOrderItemVo, count);
        OmsPostOrderItemBo add = new OmsPostOrderItemBo();
        add.setOrderId(orderId);
        add.setSkuId(skuId);
        add.setMerId(merId);
        BigDecimal amount = new BigDecimal(count).multiply(price);
        add.setOrderItemId(orderItemId);
        add.setRefundAmount(amount);
        add.setActRefundAmount(amount);
        add.setRefundCount(count);
        add.setUserId(userId);
        add.setSkuName(skuName);
        add.setSkuImage(picUrl);
        add.setSpuId(spuId);
        add.setSpuName(spuName);
        return add;
    }

    /**
     * 检查参数
     *
     * @param skuId
     * @param orderItemSkuId
     * @param spuId
     * @param orderItemSpuId
     * @param omsOrderItemVo
     * @param count
     */
    private void checkParams(Long skuId, Long orderItemSkuId, Long spuId, Long orderItemSpuId, OmsOrderItemVo omsOrderItemVo, Integer count) {
        if (ObjectUtil.notEqual(skuId, orderItemSkuId)) {
            throw new ServiceException("订单异常");
        }
        if (ObjectUtil.notEqual(spuId, orderItemSpuId)) {
            throw new ServiceException("订单异常");
        }
        Integer saleAfterNum = omsOrderItemVo.getSaleAfterNum();
        if (ObjectUtil.compare(saleAfterNum, count) < 0) {
            throw new ServiceException("商品可售后数量小于当前数量");
        }
    }
}
